package crmdna.member;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.gson.Gson;
import com.googlecode.objectify.ObjectifyFilter;

import crmdna.client.Client;
import crmdna.common.APIException;
import crmdna.common.APIResponse.Status;
import crmdna.common.OfyService;
import crmdna.common.contactdetail.ContactDetailProp;
import crmdna.group.Group;
import crmdna.group.Group.GroupProp;
import crmdna.member.MemberCore.MemberProp;
import crmdna.practice.Practice;
import crmdna.practice.Practice.PracticeProp;
import crmdna.program.Program;
import crmdna.program.ProgramProp;
import crmdna.programtype.ProgramType;
import crmdna.programtype.ProgramTypeProp;
import crmdna.sequence.Sequence;
import crmdna.sequence.Sequence.SequenceType;
import crmdna.teacher.Teacher;
import crmdna.teacher.Teacher.TeacherProp;
import crmdna.user.User;
import crmdna.user.User.Action;
import crmdna.user.User.ResourceType;
import crmdna.user.UserCore;
import crmdna.venue.Venue;
import crmdna.venue.Venue.VenueProp;

public class MemberTest {

	private final LocalServiceTestHelper datastoreHelper = new LocalServiceTestHelper(
			new LocalDatastoreServiceTestConfig().setApplyAllHighRepJobPolicy());

	private final String client = "isha";
	private final String invalidClient = "invalid";
	private final String validUser = "valid@login.com";
	private final String validUser2 = "valid2@login.com";
	private final String invalidUser = "invalid@login.com";
	private final String userWithPermission = "userwithpermission@login.com";
	private GroupProp sgp;
	private GroupProp kl;
	private GroupProp sydney;
	private GroupProp iyc;

	private PracticeProp shambhavi, mysticEye, ishaKriya;

	private ProgramTypeProp shambhavi2Day, mysticEye1Day;

	ProgramProp shambhavi201405, mysticEye201401, sathsang201405;

	MemberProp thulasi;
	String sgpUser = "sgpuser@valid.com";

	@Before
	public void setUp() {
		datastoreHelper.setUp();
		ObjectifyFilter.complete();

		Client.create(client);
		sgp = Group.create(client, "Singapore", User.SUPER_USER);
		assertEquals(1, sgp.groupId);

		kl = Group.create(client, "Malaysia/KL", User.SUPER_USER);
		assertEquals(2, kl.groupId);

		sydney = Group.create(client, "Australia/Sydney", User.SUPER_USER);
		assertEquals(3, sydney.groupId);

		iyc = Group.create(client, "India/Isha Yoga Center", User.SUPER_USER);
		assertEquals(4, iyc.groupId);

		User.create(client, validUser, sgp.groupId, User.SUPER_USER);
		assertEquals(1, UserCore.get(client, validUser).toProp().userId);

		User.create(client, validUser2, sgp.groupId, User.SUPER_USER);
		assertEquals(2, UserCore.get(client, validUser2).toProp().userId);

		User.create(client, userWithPermission, sgp.groupId, User.SUPER_USER);
		assertEquals(3,
				UserCore.get(client, userWithPermission).toProp().userId);
		User.addOrDeletePrivilege(client, userWithPermission,
				ResourceType.INTERACTION, 0, Action.WRITE, true,
				User.SUPER_USER);

		shambhavi = Practice.create("isha", "Shambhavi", User.SUPER_USER);
		mysticEye = Practice.create("isha", "MysticEye", User.SUPER_USER);
		ishaKriya = Practice.create("isha", "IshaKriya", User.SUPER_USER);

		Set<Long> sathsangPracticeIds = new HashSet<>();
		sathsangPracticeIds.add(shambhavi.practiceId);
		sathsangPracticeIds.add(mysticEye.practiceId);

		Set<Long> practiceIds = new HashSet<>();
		practiceIds.add(shambhavi.practiceId);
		ProgramTypeProp shambhavi2Day = ProgramType.create("isha", "Shambhavi",
				practiceIds, User.SUPER_USER);

		practiceIds.clear();
		practiceIds.add(mysticEye.practiceId);
		ProgramTypeProp mysticEye1Day = ProgramType.create("isha", "MysticEye",
				practiceIds, User.SUPER_USER);

		ProgramTypeProp sathsang = ProgramType.create("isha", "Sathsang", null,
				User.SUPER_USER);

		GroupProp chennai = Group.create("isha", "Chennai", User.SUPER_USER);

		VenueProp giis = Venue.create("isha", "GIIS", "GIIS", sgp.groupId,
				User.SUPER_USER);
		VenueProp expo = Venue.create("isha", "Expo", "Expo", sgp.groupId,
				User.SUPER_USER);

		TeacherProp nidhi = Teacher.create("isha",
				"nidhi.jain@ishafoundation.org", sgp.groupId, User.SUPER_USER);
		TeacherProp sadhguru = Teacher.create("isha",
				"sadhguru@ishafoundation.org", sgp.groupId, User.SUPER_USER);

		shambhavi201405 = Program.create("isha", sgp.groupId,
				shambhavi2Day.programTypeId, giis.venueId, nidhi.teacherId,
				20140503, 20140504, 1, null, 0, null, User.SUPER_USER);

		mysticEye201401 = Program.create("isha", sgp.groupId,
				mysticEye1Day.programTypeId, expo.venueId, sadhguru.teacherId,
				20140503, 20140504, 1, null, 0, null, User.SUPER_USER);

		sathsang201405 = Program.create("isha", sgp.groupId,
				sathsang.programTypeId, giis.venueId, nidhi.teacherId,
				20140503, 20140503, 1, null, 0, null, User.SUPER_USER);

		User.create("isha", sgpUser, sgp.groupId, User.SUPER_USER);
		User.addOrDeletePrivilege("isha", sgpUser, ResourceType.GROUP,
				sgp.groupId, Action.WRITE, true, User.SUPER_USER);
	}

	@After
	public void tearDown() {
		ObjectifyFilter.complete();
		datastoreHelper.tearDown();
	}

	@Test
	public void createTest() {
		// client should be valid
		try {
			Member.create(invalidClient, sgp.groupId, null, invalidUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}

		// should not be invalid user
		try {
			Member.create(client, sgp.groupId, null, invalidUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
		}

		// group id should be valid
		try {
			Member.create(client, 100, null, validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}

		// contact details should be valid
		ContactDetailProp contact = new ContactDetailProp();
		contact.firstName = "sathya"; // no email or phone number
		try {
			Member.create(client, sgp.groupId, contact, validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}

		contact.email = "sathya.t@ishafoundation.org";
		MemberProp prop = Member
				.create(client, sgp.groupId, contact, validUser);

		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals("sathya.t@ishafoundation.org", prop.contact.email);

		// cannot add the same email again
		try {
			Member.create(client, sgp.groupId, contact, validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_ALREADY_EXISTS, ex.statusCode);
		}

		// can add member without email but with valid phone number
		contact.email = null;
		contact.homePhone = "+6565227030";
		prop = Member.create(client, sgp.groupId, contact, validUser);

		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals("+6565227030", prop.contact.homePhone);
		assertEquals(null, prop.contact.email);

		// can add email again if allowDuplicateEmail is true
		contact.email = "sathya.t@ishafoundation.org";
		prop = Member.createAllowDuplicateEmail(client, sgp.groupId, contact,
				validUser);
		assertEquals("sathya.t@ishafoundation.org", prop.contact.email);
	}

	@Test
	public void updateContactDetailsTest() {
		ContactDetailProp contact = new ContactDetailProp();
		contact.firstName = "sathya";
		contact.email = "sathya.t@ishafoundation.org";
		MemberProp prop = Member
				.create(client, sgp.groupId, contact, validUser);
		assertEquals(1, prop.memberId);

		// change first name
		contact = new ContactDetailProp();
		contact.firstName = "Sathyanarayanan";
		Member.updateContactDetails(client, prop.memberId, contact, validUser);
		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals("Sathyanarayanan", prop.contact.firstName);

		// multiple changes
		contact = new ContactDetailProp();
		contact.firstName = "Sathya";
		contact.lastName = "Thilakan";
		contact.mobilePhone = "+6598361844";
		contact.homePhone = "+6565227030";
		contact.officePhone = "+6563083013";
		Member.updateContactDetails(client, prop.memberId, contact, validUser);
		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals("Sathya", prop.contact.firstName);
		assertEquals("Thilakan", prop.contact.lastName);
		assertEquals("+6598361844", prop.contact.mobilePhone);
		assertEquals("+6565227030", prop.contact.homePhone);
		assertEquals("+6563083013", prop.contact.officePhone);

		// phone no cannot be invalid
		contact = new ContactDetailProp();
		contact.mobilePhone = "9384938ad";
		try {
			Member.updateContactDetails(client, prop.memberId, contact,
					validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}

		// email cannot be invalid
		contact = new ContactDetailProp();
		contact.email = "sathyafkdjf";
		try {
			Member.updateContactDetails(client, prop.memberId, contact,
					validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}

		// email cannot clash with another member
		contact = new ContactDetailProp();
		contact.firstName = "sathya isha";
		contact.email = "sathya.isha@gmail.com";
		Member.create(client, sgp.groupId, contact, validUser);

		contact = new ContactDetailProp();
		contact.email = "sathya.isha@gmail.com";
		try {
			Member.updateContactDetails(client, prop.memberId, contact,
					validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_ALREADY_EXISTS, ex.statusCode);
		}
	}

	@Test
	public void queryTest() {

		ContactDetailProp contact = new ContactDetailProp();
		contact.email = "Sathya.t@IshaFoundation.org";
		contact.mobilePhone = "+6598361844";
		contact.homePhone = "+6565227030";

		MemberProp sathya = Member.create(client, sgp.groupId, contact,
				User.SUPER_USER);
		assertEquals(1, sathya.memberId);

		try {
			Member.query("isha", "SathYa", null, null, null, null, invalidUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
		}

		// search string cannot be less than 3 char
		try {
			Member.query("isha", "Sa", null, null, null, null, validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
					ex.statusCode);
		}

		List<MemberProp> searchResults = Member.query("isha", "SathYa", null,
				null, null, null, validUser);
		assertEquals(1, searchResults.size());

		searchResults = Member.query("isha", "sathyat", null, null, null, null,
				validUser);
		assertEquals(0, searchResults.size());

		// add few more members
		contact = new ContactDetailProp();
		contact.firstName = "Amit";
		contact.email = "amit@gmail.com";
		MemberProp amit = Member.create(client, sgp.groupId, contact,
				User.SUPER_USER);
		assertEquals(2, amit.memberId);

		contact = new ContactDetailProp();
		contact.firstName = "Shiva";
		contact.email = "sjawaji@gmail.com";
		MemberProp shiva = Member.create(client, sydney.groupId, contact,
				User.SUPER_USER);
		assertEquals(3, shiva.memberId);

		contact = new ContactDetailProp();
		contact.firstName = "Anantha";
		contact.email = "anantha@gmail.com";
		MemberProp anantha = Member.create(client, kl.groupId, contact,
				User.SUPER_USER);
		assertEquals(4, anantha.memberId);

		// search for gmail without specifying group
		searchResults = Member.query("isha", "Gmail", null, null, null, null,
				validUser);
		assertEquals(3, searchResults.size());
		// should be sorted by name
		assertEquals("Amit", searchResults.get(0).contact.firstName);
		assertEquals("Anantha", searchResults.get(1).contact.firstName);
		assertEquals("Shiva", searchResults.get(2).contact.firstName);

		// search for gmail only for sgp and kl
		Set<Long> groupIds = new HashSet<>();
		groupIds.add(sgp.groupId);
		groupIds.add(kl.groupId);
		searchResults = Member.query("isha", "Gmail", groupIds, null, null, null, 
				validUser);
		assertEquals(2, searchResults.size());
		// should be sorted by name
		assertEquals("Amit", searchResults.get(0).contact.firstName);
		assertEquals("Anantha", searchResults.get(1).contact.firstName);

		// search phone number
		searchResults = Member.query("isha", "844", groupIds, null, null, null, 
				validUser); // matches sathya
		assertEquals(1, searchResults.size());
		assertEquals("sathya.t@ishafoundation.org", searchResults.get(0).name);

		// create a shambhavi program and mystic eye program
		// shambhavi;//i = Practice.create(client, "Shambhavi",
		// User.SUPER_USER);
		PracticeProp mysticEyePractice = Practice.create(client,
				"Mystic Eye Pracice", User.SUPER_USER);
		Set<Long> practiceIds = new HashSet<>();
		practiceIds.add(shambhavi.practiceId);
		ProgramTypeProp ie7day = ProgramType.create(client, "IE 7 Day",
				practiceIds, User.SUPER_USER);

		practiceIds.clear();
		practiceIds.add(mysticEyePractice.practiceId);
		ProgramTypeProp mysticEye = ProgramType.create(client, "MysticEye1Day",
				practiceIds, User.SUPER_USER);
		VenueProp notFixed = Venue.create(client, "Not Fixed", "NA",
				sgp.groupId, User.SUPER_USER);
		TeacherProp notFixed2 = Teacher.create(client, "dummy@dummy.com",
				sgp.groupId, User.SUPER_USER);
		ProgramProp ie7day2011 = Program.create(client, sgp.groupId,
				ie7day.programTypeId, notFixed.venueId, notFixed2.teacherId,
				20110505, 20110511, 1, null, 0, null, User.SUPER_USER);
		ProgramProp mysticEyeJan14 = Program.create(client, sgp.groupId,
				mysticEye.programTypeId, notFixed.venueId, notFixed2.teacherId,
				20140112, 20140112, 1, null, 0, null, User.SUPER_USER);
		Member.addOrDeleteProgram(client, sathya.memberId,
				ie7day2011.programId, true, User.SUPER_USER);
		Member.addOrDeleteProgram(client, amit.memberId, ie7day2011.programId,
				true, User.SUPER_USER);
		Member.addOrDeleteProgram(client, shiva.memberId, ie7day2011.programId,
				true, User.SUPER_USER);
		Member.addOrDeleteProgram(client, anantha.memberId,
				ie7day2011.programId, true, User.SUPER_USER);

		// mystic eye only for amit
		Member.addOrDeleteProgram(client, amit.memberId,
				mysticEyeJan14.programId, true, User.SUPER_USER);

		// search for both mysticeye - only amit
		practiceIds.add(shambhavi.practiceId);
		practiceIds.add(mysticEyePractice.practiceId);
		List<MemberProp> memberProps = Member.query(client, "amit", null,
				practiceIds, null, null, User.SUPER_USER);
		assertEquals(1, memberProps.size());

		// search for all members that are initiated into shambhavi
		practiceIds.clear();
		practiceIds.add(shambhavi.practiceId);
		memberProps = Member.query(client, null, null, practiceIds, null, null, 
				User.SUPER_USER);
		System.out.println("memberProps = " + new Gson().toJson(memberProps));
		assertEquals(4, memberProps.size());

		// limit size to 1
		memberProps = Member.query(client, null, null, practiceIds, null, 1,  
				User.SUPER_USER);
		assertEquals(1, memberProps.size());

		// limit to 4
		memberProps = Member.query(client, null, null, practiceIds, null, 4,
				User.SUPER_USER);
		assertEquals(4, memberProps.size());
		
		//query by program
		assertTrue(false);
	}

	@Test
	public void safeGetTest() {
		ContactDetailProp contact = new ContactDetailProp();
		contact.email = "Sathya.t@IshaFoundation.org";
		contact.mobilePhone = "+6598361844";
		contact.homePhone = "+6565227030";

		MemberProp prop = Member.create(client, sgp.groupId, contact,
				User.SUPER_USER);

		try {
			Member.safeGet(client, prop.memberId, invalidUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals("invalid user cannot view member",
					Status.ERROR_INVALID_USER, ex.statusCode);
		}

		prop = Member.safeGet(client, prop.memberId, validUser).toProp();
		assertEquals("sathya.t@ishafoundation.org", prop.contact.email);
		assertEquals("+6598361844", prop.contact.mobilePhone);
		assertEquals("+6565227030", prop.contact.homePhone);
	}

	@Test
	public void ofyAsyncTest() {
		MemberEntity memberEntity = new MemberEntity();
		long memberId = Sequence.getNext(client, SequenceType.MEMBER);
		memberEntity.memberId = memberId;
		memberEntity.email = "sathyanarayanant@gmail.com";

		OfyService.ofy(client).save().entity(memberEntity); // async save

		assertEquals("sathyanarayanant@gmail.com", OfyService.ofy(client)
				.load().type(MemberEntity.class).id(memberId).get().email);
		
		ObjectifyFilter.complete();
		assertEquals("sathyanarayanant@gmail.com", OfyService.ofy(client)
				.load().type(MemberEntity.class).id(memberId).get().email);
	}

	@Test
	public void addOrDeleteGroupTest() {
		ContactDetailProp contact = new ContactDetailProp();
		contact.email = "Sathya.t@IshaFoundation.org";
		contact.mobilePhone = "+6598361844";
		contact.homePhone = "+6565227030";

		MemberProp prop = Member.create(client, sgp.groupId, contact,
				User.SUPER_USER);

		// user cannot be invalid
		try {
			Member.addOrDeleteGroup(client, prop.memberId, 100, true,
					invalidUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
		}

		// member should exist
		try {
			Member.addOrDeleteGroup(client, 3456, kl.groupId, true, validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}

		// center should exist
		try {
			Member.addOrDeleteGroup(client, prop.memberId, 100, true, validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}

		// add kl
		Member.addOrDeleteGroup(client, prop.memberId, kl.groupId, true,
				validUser);
		ObjectifyFilter.complete();
		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals(2, prop.groupIds.size());
		assertTrue(prop.groupIds.contains(sgp.groupId));
		assertTrue(prop.groupIds.contains(kl.groupId));

		// can add the same center again
		Member.addOrDeleteGroup(client, prop.memberId, kl.groupId, true,
				validUser);
		ObjectifyFilter.complete();
		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals(2, prop.groupIds.size());
		assertTrue(prop.groupIds.contains(sgp.groupId));
		assertTrue(prop.groupIds.contains(kl.groupId));

		// remove center
		Member.addOrDeleteGroup(client, prop.memberId, kl.groupId, false,
				validUser);
		ObjectifyFilter.complete();
		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals(1, prop.groupIds.size());
		assertTrue(prop.groupIds.contains(sgp.groupId));
		assertTrue(!prop.groupIds.contains(kl.groupId));

		// can remove center again
		Member.addOrDeleteGroup(client, prop.memberId, kl.groupId, false,
				validUser);
		ObjectifyFilter.complete();
		prop = MemberCore.safeGet(client, prop.memberId).toProp();
		assertEquals(1, prop.groupIds.size());
		assertTrue(prop.groupIds.contains(sgp.groupId));
		assertTrue(!prop.groupIds.contains(kl.groupId));

		// there should be atleast 1 center
		try {
			Member.addOrDeleteGroup(client, prop.memberId, sgp.groupId, false,
					validUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_PRECONDITION_FAILED, ex.statusCode);
		}
	}

	@Test
	public void getAllForCenterTest() {
		// should be valid user
		try {
			Member.getAllForGroup(client, sgp.groupId, invalidUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
		}

		List<MemberProp> memberProps = Member.getAllForGroup(client,
				sgp.groupId, validUser);
		assertEquals(0, memberProps.size());

		ContactDetailProp contact = new ContactDetailProp();
		contact.email = "Sathya.t@IshaFoundation.org";
		contact.mobilePhone = "+6598361844";
		contact.homePhone = "+6565227030";
		Member.create(client, sgp.groupId, contact, validUser);

		memberProps = Member.getAllForGroup(client, sgp.groupId, validUser);
		assertEquals(1, memberProps.size());

		// add 1 more
		contact = new ContactDetailProp();
		contact.email = "amit@gmail.com";
		contact.firstName = "Amit";
		Member.create(client, sgp.groupId, contact, validUser);

		// getAllForCenter should return in sorted order
		memberProps = Member.getAllForGroup(client, sgp.groupId, validUser);
		assertEquals(2, memberProps.size());
		assertEquals("Amit", memberProps.get(0).contact.firstName);
		assertEquals("sathya.t@ishafoundation.org",
				memberProps.get(1).contact.email);
	}

	@Test
	public void populateDependantIndexFieldsTest() {

		assertTrue(false);

		// MemberEntity memberEntity = new MemberEntity();
		// try {
		// MemberCore.populateDependantIndexFields(memberEntity);
		// } catch (APIException e) {
		// assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED,
		// e.statusCode);
		// }
		//
		// //email specified but not name
		// memberEntity.email = "emailsathya@gmail.com";
		// MemberCore.populateDependantIndexFields(memberEntity);
		// assertEquals(memberEntity.name, memberEntity.email);
		// assertEquals(memberEntity.nameFirstChar, "e");
		//
		// //specify phone number but not email or name
		// memberEntity = new MemberEntity();
		// memberEntity.mobilePhone = "+6598361844";
		// MemberCore.populateDependantIndexFields(memberEntity);
		// assertEquals(memberEntity.name, memberEntity.mobilePhone);
		// assertEquals(memberEntity.nameFirstChar, "+");
		//
		// //specify name and email
		// memberEntity = new MemberEntity();
		// memberEntity.firstName = "Sathyanarayanan";
		// memberEntity.email = "sathya.t@ishafoundation.org";
		// MemberCore.populateDependantIndexFields(memberEntity);
		// assertEquals(memberEntity.name, "sathyanarayanan");
		// assertEquals(memberEntity.nameFirstChar, "s");
	}

	@Test
	public void addOrDeleteProgramTest_toberemoved() {
		assertTrue(false);
	}

	@Test
	public void bulkUploadParticipantsTest() {
		assertEquals(true, false);
	}

	@Test
	public void bulkUpdateWithoutValidations() {
		assertTrue(false);
	}

	@Test
	public void bulkUploadProgramParticipants() {
		assertTrue(false);
	}

	@Test
	public void ensureValidTest() {
		assertTrue(false);
	}

	@Test
	public void addOrDeleteProgramTest() {
		ContactDetailProp contactDetailProp = new ContactDetailProp();
		contactDetailProp.email = "simansmile@yahoo.com";

		MemberProp narasimhan = Member.create(client, sgp.groupId,
				contactDetailProp, User.SUPER_USER);

		contactDetailProp.email = "thulasidhar@gmail.com";
		MemberProp thulasi = Member.create(client, sgp.groupId,
				contactDetailProp, User.SUPER_USER);

		VenueProp adiYogiAlayam = Venue.create(client, "Adi yogi aalayam",
				"Adi yogi aalamay", iyc.groupId, User.SUPER_USER);

		PracticeProp suryaKriya = Practice.create(client, "surya kriya",
				User.SUPER_USER);
		PracticeProp upaYoga = Practice.create(client, "upa yoga",
				User.SUPER_USER);
		PracticeProp angamardhana = Practice.create(client, "angamardhana",
				User.SUPER_USER);
		PracticeProp yogaAsanas = Practice.create(client, "yoga asanas",
				User.SUPER_USER);

		Set<Long> practiceIds = new HashSet<Long>();
		practiceIds.add(suryaKriya.practiceId);
		practiceIds.add(upaYoga.practiceId);
		practiceIds.add(angamardhana.practiceId);
		practiceIds.add(yogaAsanas.practiceId);

		ProgramTypeProp hatayoga21day = ProgramType.create(client,
				"Hata yoga 21 day", practiceIds, User.SUPER_USER);

		TeacherProp sheela = Teacher.create(client,
				"sheela.r@ishafoundation.org", iyc.groupId, User.SUPER_USER);

		ProgramProp hatayoga21day2013 = Program.create(client, iyc.groupId,
				hatayoga21day.programTypeId, adiYogiAlayam.venueId,
				sheela.teacherId, 20130701, 20130721, 1, null, 0, null,
				User.SUPER_USER);

		List<Long> memberIds = new ArrayList<Long>();

		// can call with empty list
		Member.addOrDeleteProgram(client, hatayoga21day2013.programId,
				memberIds, true, User.SUPER_USER);

		memberIds.add(narasimhan.memberId);
		memberIds.add(thulasi.memberId);
		memberIds.add((long) 100); // invalid member id

		Member.addOrDeleteProgram(client, hatayoga21day.programTypeId,
				memberIds, true, validUser);

		// clear session cache
		ObjectifyFilter.complete();
		OfyService.ofy(client).clear();

		MemberProp thulasiProp = Member.safeGet(client, thulasi.memberId,
				User.SUPER_USER).toProp();
		assertEquals(1, thulasiProp.programIds.size());
		assertTrue(thulasiProp.programIds.contains(hatayoga21day2013.programId));
		assertEquals(1, thulasiProp.programTypeIds.size());
		assertTrue(thulasiProp.programTypeIds
				.contains(hatayoga21day.programTypeId));
		assertEquals(4, thulasiProp.practiceIds.size());
		assertTrue(thulasiProp.practiceIds.contains(suryaKriya.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(upaYoga.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(angamardhana.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(yogaAsanas.practiceId));

		MemberProp narasimhanProp = Member.safeGet(client, narasimhan.memberId,
				User.SUPER_USER).toProp();
		assertEquals(1, narasimhanProp.programIds.size());
		assertTrue(narasimhanProp.programIds
				.contains(hatayoga21day2013.programId));
		assertEquals(1, narasimhanProp.programTypeIds.size());
		assertTrue(narasimhanProp.programTypeIds
				.contains(hatayoga21day.programTypeId));
		assertEquals(4, narasimhanProp.practiceIds.size());
		assertTrue(narasimhanProp.practiceIds.contains(suryaKriya.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(upaYoga.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(angamardhana.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(yogaAsanas.practiceId));

		// add again
		Member.addOrDeleteProgram(client, hatayoga21day.programTypeId,
				memberIds, true, validUser);
		ObjectifyFilter.complete();
		OfyService.ofy(client).clear();

		thulasiProp = Member.safeGet(client, thulasi.memberId, User.SUPER_USER)
				.toProp();
		assertEquals(1, thulasiProp.programIds.size());
		assertTrue(thulasiProp.programIds.contains(hatayoga21day2013.programId));
		assertEquals(1, thulasiProp.programTypeIds.size());
		assertTrue(thulasiProp.programTypeIds
				.contains(hatayoga21day.programTypeId));
		assertEquals(4, thulasiProp.practiceIds.size());
		assertTrue(thulasiProp.practiceIds.contains(suryaKriya.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(upaYoga.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(angamardhana.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(yogaAsanas.practiceId));

		narasimhanProp = Member.safeGet(client, narasimhan.memberId,
				User.SUPER_USER).toProp();
		assertEquals(1, narasimhanProp.programIds.size());
		assertTrue(narasimhanProp.programIds
				.contains(hatayoga21day2013.programId));
		assertEquals(1, narasimhanProp.programTypeIds.size());
		assertTrue(narasimhanProp.programTypeIds
				.contains(hatayoga21day.programTypeId));
		assertEquals(4, narasimhanProp.practiceIds.size());
		assertTrue(narasimhanProp.practiceIds.contains(suryaKriya.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(upaYoga.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(angamardhana.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(yogaAsanas.practiceId));

		// delete member
		Member.addOrDeleteProgram(client, hatayoga21day.programTypeId,
				memberIds, true, validUser);
		ObjectifyFilter.complete();
		OfyService.ofy(client).clear();

		// exception if client is invalid
		try {
			Member.addOrDeleteProgram(invalidClient,
					hatayoga21day2013.programId, memberIds, true,
					User.SUPER_USER);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}

		// program id should be valid
		try {
			Member.addOrDeleteProgram(client, 938, memberIds, true,
					User.SUPER_USER); // invalid program id
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}

		// user should be a valid user
		try {
			Member.addOrDeleteProgram(client, hatayoga21day2013.programId,
					memberIds, true, invalidUser);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
		}
	}

	@Test
	public void bulkCreateWithoutValidationsTest() {

		ContactDetailProp thulasi = new ContactDetailProp();
		thulasi.email = "thulasidhar@gmail.com";
		thulasi.firstName = "Thulasidhar";
		thulasi.lastName = "Kosalram";
		thulasi.mobilePhone = "+6592705371";

		ContactDetailProp narasimhan = new ContactDetailProp();
		narasimhan.email = "simansmile@yahoo.com";
		narasimhan.firstName = "Narasimhan";
		narasimhan.mobilePhone = "+6597302205";

		VenueProp adiYogiAlayam = Venue.create(client, "Adi yogi aalayam",
				"Adi yogi aalamay", iyc.groupId, User.SUPER_USER);

		PracticeProp suryaKriya = Practice.create(client, "surya kriya",
				User.SUPER_USER);
		PracticeProp upaYoga = Practice.create(client, "upa yoga",
				User.SUPER_USER);
		PracticeProp angamardhana = Practice.create(client, "angamardhana",
				User.SUPER_USER);
		PracticeProp yogaAsanas = Practice.create(client, "yoga asanas",
				User.SUPER_USER);

		Set<Long> practiceIds = new HashSet<Long>();
		practiceIds.add(suryaKriya.practiceId);
		practiceIds.add(upaYoga.practiceId);
		practiceIds.add(angamardhana.practiceId);
		practiceIds.add(yogaAsanas.practiceId);

		ProgramTypeProp hatayoga21day = ProgramType.create(client,
				"Hata yoga 21 day", practiceIds, User.SUPER_USER);

		TeacherProp sheela = Teacher.create(client,
				"sheela.r@ishafoundation.org", iyc.groupId, User.SUPER_USER);

		ProgramProp hatayoga21day2013 = Program.create(client, iyc.groupId,
				hatayoga21day.programTypeId, adiYogiAlayam.venueId,
				sheela.teacherId, 20130701, 20130721, 1, null, 0, null,
				User.SUPER_USER);

		List<ContactDetailProp> contactDetailProps = new ArrayList<ContactDetailProp>();
		contactDetailProps.add(null);
		contactDetailProps.add(null);

		Member.bulkCreateWithoutValidations(client, contactDetailProps,
				hatayoga21day2013.programId);

		contactDetailProps.clear();
		contactDetailProps.add(null);
		contactDetailProps.add(thulasi);
		contactDetailProps.add(null);
		contactDetailProps.add(narasimhan);
		contactDetailProps.add(null);

		List<Long> memberIds = Member.bulkCreateWithoutValidations(client,
				contactDetailProps, hatayoga21day2013.programId);
		assertEquals(5, memberIds.size());
		// same order should be preserved
		assertEquals(null, memberIds.get(0));
		assertEquals(1, memberIds.get(1) + 0);
		assertEquals(null, memberIds.get(2));
		assertEquals(2, memberIds.get(3) + 0);
		assertEquals(null, memberIds.get(4));

		// clear cache
		ObjectifyFilter.complete();
		OfyService.ofy(client).clear();

		MemberProp thulasiProp = Member.safeGet(client, 1, User.SUPER_USER)
				.toProp();
		assertEquals("thulasidhar@gmail.com", thulasiProp.contact.email);
		assertEquals("Thulasidhar Kosalram", thulasiProp.contact.firstName
				+ " " + thulasiProp.contact.lastName);
		assertEquals("+6592705371", thulasiProp.contact.mobilePhone);
		assertEquals(1, thulasiProp.programIds.size());
		assertTrue(thulasiProp.programIds.contains(hatayoga21day2013.programId));
		assertEquals(1, thulasiProp.programTypeIds.size());
		assertTrue(thulasiProp.programTypeIds
				.contains(hatayoga21day.programTypeId));
		assertEquals(4, thulasiProp.practiceIds.size());
		assertTrue(thulasiProp.practiceIds.contains(suryaKriya.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(upaYoga.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(yogaAsanas.practiceId));
		assertTrue(thulasiProp.practiceIds.contains(angamardhana.practiceId));

		List<MemberProp> matches = Member.query(client, "thulasidhar", null,
				null, null, null, validUser);
		assertEquals(1, matches.size());
		assertEquals(thulasiProp.memberId, matches.get(0).memberId);

		MemberProp narasimhanProp = Member.safeGet(client, 2, User.SUPER_USER)
				.toProp();
		assertEquals("simansmile@yahoo.com", narasimhanProp.contact.email);
		assertEquals("Narasimhan", narasimhanProp.contact.firstName);
		assertEquals("+6597302205", narasimhanProp.contact.mobilePhone);
		assertEquals(1, narasimhanProp.programIds.size());
		assertTrue(narasimhanProp.programIds
				.contains(hatayoga21day2013.programId));
		assertEquals(1, narasimhanProp.programTypeIds.size());
		assertTrue(narasimhanProp.programTypeIds
				.contains(hatayoga21day.programTypeId));
		assertEquals(4, narasimhanProp.practiceIds.size());
		assertTrue(narasimhanProp.practiceIds.contains(suryaKriya.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(upaYoga.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(yogaAsanas.practiceId));
		assertTrue(narasimhanProp.practiceIds.contains(angamardhana.practiceId));

		// exception if client is invalid
		try {
			Member.bulkCreateWithoutValidations(invalidClient,
					contactDetailProps, hatayoga21day2013.programId);
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}

		// program id should be valid
		try {
			Member.bulkCreateWithoutValidations(client, contactDetailProps, 992); // invalid
																					// program
																					// id
			assertTrue(false);
		} catch (APIException ex) {
			assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
	}

	@Test
	public void getMatchingMemberIdsTest() {
		ContactDetailProp contactDetailProp = new ContactDetailProp();
		List<ContactDetailProp> contactDetailProps = new ArrayList<>();

		List<Long> matching = Member.getMatchingMemberIds(client,
				contactDetailProps);
		assertEquals(0, matching.size());

		contactDetailProps.clear();
		contactDetailProp.email = "sathya.t@ishafoundation.org";
		contactDetailProps.add(contactDetailProp);
		matching = Member.getMatchingMemberIds(client, contactDetailProps);
		assertEquals(1, matching.size());
		assertEquals(null, matching.get(0));

		ContactDetailProp c = new ContactDetailProp();
		c.firstName = "Sathyanarayanan";
		c.lastName = "Thilakan";
		c.email = "sathya.t@ishafoundation.org";
		c.mobilePhone = "+6593232152";
		MemberProp sathya = Member.create(client, sgp.groupId, c,
				User.SUPER_USER);

		c = new ContactDetailProp();
		c.firstName = "Thulasidhar";
		c.lastName = "Kosalram";
		c.email = "thulasidhar@gmail.com";
		c.mobilePhone = "+6593705371";
		MemberProp thulasi = Member.create(client, sgp.groupId, c,
				User.SUPER_USER);

		c = new ContactDetailProp();
		c.firstName = "Sharmila";
		c.lastName = "Napa";
		c.email = "sharmila@bhairaviyoga.sg";
		MemberProp sharmila = Member.create(client, sgp.groupId, c,
				User.SUPER_USER);

		// create contacts
		ContactDetailProp syamala = new ContactDetailProp();
		syamala.firstName = "syamala";
		syamala.mobilePhone = "+6593232152";

		ContactDetailProp thilakan = new ContactDetailProp();
		thilakan.firstName = "thilakan";
		thilakan.email = "rthilakan@gmail.com";

		ContactDetailProp sowmya = new ContactDetailProp();
		sowmya.firstName = "sowmya ramakrishnan";
		sowmya.email = "sathya.t@ishafoundation.org";

		ContactDetailProp sathyaContactDetail = new ContactDetailProp();
		sathyaContactDetail.firstName = "sathya";
		sathyaContactDetail.mobilePhone = "+6593232152";

		contactDetailProps.clear();
		contactDetailProps.add(syamala);
		contactDetailProps.add(thilakan);
		contactDetailProps.add(sowmya);
		contactDetailProps.add(sathyaContactDetail);
		contactDetailProps.add(thulasi.contact);
		contactDetailProps.add(sharmila.contact);

		List<Long> matchingMemberIds = Member.getMatchingMemberIds(client,
				contactDetailProps);
		assertEquals(6, matchingMemberIds.size());
		assertEquals(null, matchingMemberIds.get(0));
		assertEquals(null, matchingMemberIds.get(1));
		assertEquals(null, matchingMemberIds.get(2));
		assertEquals(new Long(sathya.memberId), matchingMemberIds.get(3));
		assertEquals(new Long(thulasi.memberId), matchingMemberIds.get(4));
		assertEquals(new Long(sharmila.memberId), matchingMemberIds.get(5));
	}
}
